package com.clei.Y2023.M10.D13.com;

import com.clei.Y2023.M10.D13.packet.PacketHandler;
import com.clei.utils.PrintUtil;
import gnu.io.SerialPort;
import gnu.io.SerialPortEvent;
import gnu.io.SerialPortEventListener;

import java.io.InputStream;
import java.util.concurrent.BlockingQueue;

/**
 * 串口消息监听
 *
 * @author Y
 * @date 2023-10-24
 */
public class ComMessageListener implements SerialPortEventListener {

    /**
     * InputStream
     */
    private InputStream inputStream;

    /**
     * 阻塞队列
     */
    private final BlockingQueue<String> msgQueue;

    /**
     * 包处理器
     */
    private final PacketHandler packetHandler;

    public ComMessageListener(SerialPort serialPort, BlockingQueue<String> msgQueue, PacketHandler packetHandler) {
        this.msgQueue = msgQueue;
        this.packetHandler = packetHandler;
        try {
            this.inputStream = serialPort.getInputStream();
        } catch (Exception e) {
            PrintUtil.log("获取输入流出错 ", e);
        }
    }

    @Override
    public void serialEvent(SerialPortEvent event) {
        switch (event.getEventType()) {
            /*
             *  SerialPortEvent.BI:/*Break interrupt,通讯中断
             *  SerialPortEvent.OE:/*Overrun error，溢位错误
             *  SerialPortEvent.FE:/*Framing error，传帧错误
             *  SerialPortEvent.PE:/*Parity error，校验错误
             *  SerialPortEvent.CD:/*Carrier detect，载波检测
             *  SerialPortEvent.CTS:/*Clear to send，清除发送
             *  SerialPortEvent.DSR:/*Data set ready，数据设备就绪
             *  SerialPortEvent.RI:/*Ring indicator，响铃指示
             *  SerialPortEvent.OUTPUT_BUFFER_EMPTY:/*Output buffer is empty，输出缓冲区清空
             */
            case SerialPortEvent.BI:
            case SerialPortEvent.OE:
            case SerialPortEvent.FE:
            case SerialPortEvent.PE:
            case SerialPortEvent.CD:
            case SerialPortEvent.CTS:
            case SerialPortEvent.DSR:
            case SerialPortEvent.RI:
            case SerialPortEvent.OUTPUT_BUFFER_EMPTY:
                break;
            // 当有可用数据时读取数据
            case SerialPortEvent.DATA_AVAILABLE:
                // 数据接收缓冲容器
                int available = 0;
                try {
                    available = inputStream.available();
                    if (available <= 0) {
                        break;
                    }
                    byte[] data = new byte[available];
                    inputStream.read(data);

                    // 包处理
                    this.packetHandler.packetHandle(msgQueue, data);
                } catch (Exception e) {
                    PrintUtil.log("data read error ", e);
                }
                break;
        }
    }
}
